package com.hclc.yxb.shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hclc.entity.model.SysUserModel;
import com.hclc.entity.model.contans.ApiConst;
import com.hclc.yxb.mapper.*;
import com.hclc.yxb.model.SysMenuModel;
import com.hclc.yxb.model.SysRoleMenuModel;
import com.hclc.yxb.model.SysRoleModel;
import com.hclc.yxb.model.SysUserRoleModel;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author lixin
 * @version V1.0
 * @ClassName: MyAuthRealm
 * @Description: TODO(shiro realm)
 * @date 2019年7月17日 上午10:25:38
 */
public class MyAuthRealm extends AuthorizingRealm {

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
            throws AuthenticationException {
        // 拿到登录用户信息
        UsernamePasswordToken upToken = (UsernamePasswordToken) authcToken;
        String account = upToken.getUsername();
        if (StringUtils.isNotBlank(account)) {
            // 查询对应用户信息
            SysUserModel user = selectCurrentLoginUserInfo(account);
            if (Objects.nonNull(user) && Objects.nonNull(user.getUserPass())) {
                String password = user.getUserPass();
                // 返回对应用户凭证
                return new SimpleAuthenticationInfo(user, password, getName());
            }
        }
        return null;
    }

    /**
     * 授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUserModel user = (SysUserModel) principals.getPrimaryPrincipal();

        SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();

        Map<String, SysUserRoleModel> userRoleMap = sysUserRoleMapper.selectList(new QueryWrapper<SysUserRoleModel>()
                .lambda()
                .eq(SysUserRoleModel::getUserId, user.getId())
                .eq(SysUserRoleModel::getEnable, ApiConst.ENABLE_TRUE)
        ).parallelStream().collect(Collectors.toMap(s -> s.getRoleId(), s -> s));

        if (userRoleMap.size() == 0) {
            return authInfo;
        }

        Map<String, SysRoleModel> roleInfoMap = sysRoleMapper.selectBatchIds(userRoleMap.keySet()).parallelStream().collect(Collectors.toMap(s -> s.getId(), s -> s));

        List<SysRoleMenuModel> sysRoleMenuModels = sysRoleMenuMapper.selectList(new QueryWrapper<SysRoleMenuModel>()
                .lambda()
                .eq(SysRoleMenuModel::getEnable, ApiConst.ENABLE_TRUE)
                .in(SysRoleMenuModel::getRoleId, userRoleMap.keySet())
        );

        Map<String, List<SysRoleMenuModel>> menuGroupByRole = sysRoleMenuModels.parallelStream().collect(Collectors.groupingBy(SysRoleMenuModel::getRoleId));

        Set<String> menuIds = sysRoleMenuModels.parallelStream().map(s -> s.getMenuId()).collect(Collectors.toSet());

        Map<String, SysMenuModel> menuMap = new HashMap<>();
        if (menuIds.size() > 0) {
            menuMap.putAll(sysMenuMapper.selectList(new QueryWrapper<SysMenuModel>()
                    .lambda()
                    .eq(SysMenuModel::getEnable, ApiConst.ENABLE_TRUE)
                    .in(SysMenuModel::getId, menuIds)
            ).parallelStream().collect(Collectors.toMap(s -> s.getId(), s -> s)));
        }

        userRoleMap.keySet().stream().forEach(s -> {
            menuGroupByRole.get(s).stream().forEach(i -> {
                SysMenuModel sysMenuModel = Optional.ofNullable(menuMap.get(i)).orElse(new SysMenuModel());
                if (Strings.isNotBlank(sysMenuModel.getPermName())) {
                    authInfo.addRole(roleInfoMap.get(s).getRoleName());
                    authInfo.addStringPermission(sysMenuModel.getPermName());
                }

            });
        });

        return authInfo;
    }

    /**
     * 获取当前用户登录信息
     *
     * @param userName
     * @return com.hclc.pwl.model.SysUserModel
     * @author yurj
     * @mail 1638234804@qq.com
     * @version 1.0
     * @date 2020/8/19 11:16
     */
    private SysUserModel selectCurrentLoginUserInfo(String userName) {
        // 当前登录用户
        SysUserModel sysUserModel = sysUserMapper.selectOne(new QueryWrapper<SysUserModel>()
                .lambda()
                .eq(SysUserModel::getEnable, ApiConst.ENABLE_TRUE)
                .eq(SysUserModel::getUserName, userName)
        );
        Optional.ofNullable(sysUserModel).orElseThrow(() -> new AuthenticationException("无效用户"));
        return sysUserModel;
    }
}
